package knowlwdge_graph.knowledge_etl.yago_etl;

import common.dao.orient.OrientJDBCDao;
import org.slf4j.LoggerFactory;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;

/**
 * Created by julianzliu on 4/15/2017.
 */
public class LoderOrientDB {

    static final org.slf4j.Logger logger = LoggerFactory.getLogger(LoderOrientDB.class);

    private OrientJDBCDao orientJDBCDao;
    private Connection conn;

    public LoderOrientDB(){
        this.orientJDBCDao = new OrientJDBCDao();
        this.conn = this.orientJDBCDao.getConn();
    }

    public void saveTripleTuple(RowYagoTriple triple){
        String subject = triple.subject;
        String predicate = triple.predicate;
        String object = triple.object;
        String tripleid = triple.id;
        Float value = triple.value;

        String subject_rid = getVertexRIDByID(subject);
        String object_id = getVertexRIDByID(object);
        String predicate_id = getRIDByID("E", tripleid);

        if( SchemaDefinition.YAGO_LABEL_EDGE.label_set.contains( predicate ) ){  //rdfs:label
            if(object_id == null){
                createLabelVertex(object);
                object_id = getVertexRIDByID(object);
            }
            if(subject_rid == null){
                createVertex(subject);
                subject_rid = getVertexRIDByID(subject);
            }
            if(predicate_id == null)
                createEdge(tripleid, predicate, subject_rid, object_id, value);
        }
        else if(SchemaDefinition.YAGO_CONCEPT_EDGE.label_set.contains( predicate )) {  //rdf:type
            if(object_id == null){
                createConceptVertex(object);
                object_id = getVertexRIDByID(object_id);
            }else{
                updateVertexType(object_id, SchemaDefinition.YAGO_NODE_TYPE.TYPE_CONCEPT);
            }
            if(subject_rid == null){
                createVertex(subject);
                subject_rid = getVertexRIDByID(subject);
            }
            if(predicate_id == null)
                createEdge(tripleid, predicate, subject_rid, object_id, value);

        }
        else{
            if(object_id == null){
                createVertex(object);
                object_id = getVertexRIDByID(object);
            }
            if(subject_rid == null){
                createVertex(subject);
                subject_rid = getVertexRIDByID(subject);
            }
            if(predicate_id == null)
                createEdge(tripleid, predicate, subject_rid, object_id, value);
        }

    }


    public String getRIDByID(String class_name, String yago_id){
        String sql = String.format("select @rid from %s where yago_id = '%s'", class_name, yago_id);
        logger.debug("[getRIDByID] sql = {}", sql );

        Statement stmt = null;
        ResultSet rs = null;
        String rid = null;

        try {
            stmt = this.conn.createStatement();
            rs = stmt.executeQuery(sql);
            while (rs.next()) {
                rid = rs.getString("rid");
            }
            rs.close();
            stmt.close();
        }
        catch (Exception e){
            e.printStackTrace();
        }
        return rid;
    }


    public String getVertexRIDByID(String yago_id){
        return getRIDByID("V", yago_id);
    }

    public String getEdgeRIDByID(String yago_id){
        return getRIDByID("E", yago_id);
    }


    public boolean updateVertexType(String orientdb_id, String YAGO_NODE_TYPE){
        /*
        无法更改先前创建的 record 的 Class。 只能更改字段
         */
        String sql = String.format("UPDATE %s SET %s='%s'",  orientdb_id, SchemaDefinition.COMMON.PROPERTY_YAGO_TYPE, YAGO_NODE_TYPE);
        logger.debug("[updateVertexType] sql = {}", sql );

        Statement stmt = null;
        boolean success = true;
        try {
            stmt = this.conn.createStatement();
            success = stmt.execute(sql);
            stmt.close();
        }
        catch (Exception e){
            e.printStackTrace();
        }
        return success;
    }

    public boolean createVertex(String yago_id){
        String sql = String.format("CREATE VERTEX %s SET yago_id = '%s', yago_label = '%s', yago_type='%s'",
                SchemaDefinition.YAGO_OTHER_CLASS.CLASS_NAME, yago_id, yago_id, SchemaDefinition.YAGO_NODE_TYPE.TYPE_OTHER);
        logger.debug("[createVertex] sql = {}", sql );

        Statement stmt = null;
        boolean success = true;
        try {
            stmt = this.conn.createStatement();
            success = stmt.execute(sql);
            stmt.close();
        }
        catch (Exception e){
            e.printStackTrace();
        }
        return success;
    }

    public boolean createLabelVertex(String yago_id){
        String sql = String.format("CREATE VERTEX %s SET %s='%s', %s='%s', %s='%s'",
                SchemaDefinition.YAGO_LABEL_CLASS.CLASS_NAME,
                SchemaDefinition.YAGO_LABEL_CLASS.PROPERTY_YAGO_ID, yago_id,
                SchemaDefinition.YAGO_LABEL_CLASS.PROPERTY_YAGO_LABEL, yago_id,
                SchemaDefinition.YAGO_LABEL_CLASS.PROPERTY_YAGO_TYPE, SchemaDefinition.YAGO_NODE_TYPE.TYPE_LABEL);

        logger.debug("[createLabelVertex] sql = {}", sql );

        Statement stmt = null;
        boolean success = true;
        try {
            stmt = this.conn.createStatement();
            success = stmt.execute(sql);
            stmt.close();
        }
        catch (Exception e){
            e.printStackTrace();
        }
        return success;
    }

    public boolean createConceptVertex(String yago_id){
        String sql = String.format("CREATE VERTEX %s SET %s='%s', %s='%s', %s='%s'",
                SchemaDefinition.YAGO_CONCEPT_CLASS.CLASS_NAME,
                SchemaDefinition.YAGO_CONCEPT_CLASS.PROPERTY_YAGO_ID, yago_id,
                SchemaDefinition.YAGO_CONCEPT_CLASS.PROPERTY_YAGO_LABEL, yago_id,
                SchemaDefinition.YAGO_CONCEPT_CLASS.PROPERTY_YAGO_TYPE, SchemaDefinition.YAGO_NODE_TYPE.TYPE_CONCEPT);

        logger.debug("[createConceptVertex] sql = {}", sql );

        Statement stmt = null;
        boolean success = true;
        try {
            stmt = this.conn.createStatement();
            success = stmt.execute(sql);
            stmt.close();
        }
        catch (Exception e){
            e.printStackTrace();
        }
        return success;
    }


    public boolean createEdge(String yago_id, String yago_label, String head_rid, String tail_rid, Float value){
        String sql = String.format("CREATE EDGE %s FROM %s TO %s SET yago_id = '%s', yago_label = '%s', value = %f",
                SchemaDefinition.YAGO_OTHER_EDGE.EDGE_NAME,
                head_rid, tail_rid, yago_id, yago_label, value);
        logger.debug("[createEdge] sql = {}", sql );

        Statement stmt = null;
        boolean success = true;
        try {
            stmt = this.conn.createStatement();
            success = stmt.execute(sql);
            stmt.close();
        }
        catch (Exception e){
            e.printStackTrace();
        }
        return success;

    }


    public boolean linkEdgeWithPartnerVertex(String yago_id, String vertex_rid){
        /*
        1） 如果某个三元组中出现的主语或者宾语为 另外一个三元组的ID
        2) 建立一个节点，关联这个伙伴节点和边（三元组id）
         */
        String edge_id = getEdgeRIDByID(yago_id);
        if(edge_id == null){
            return true;
        }

        String sql = String.format("");
        logger.debug("[linkEdgeWithPartnerVertex] sql = {}", sql );

        Statement stmt = null;
        boolean success = true;
        try {
            stmt = this.conn.createStatement();
            success = stmt.execute(sql);
            stmt.close();
        }
        catch (Exception e){
            e.printStackTrace();
        }
        return success;


    }



}
